package com.yuxi.common.token;


import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.yuxi.common.StringUtil;
import com.yuxi.common.redis.RedisUtil;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;

/**
 * @author sunke
 * @Date 2019/11/12 10:50
 * @description
 */

@Component
public class JwtsUtil {

    public static String ADMIN_SECRET = "adminsecret";
    public static String ADMIN_HEADER_KEY = "adminauthorization";
    public static String ADMIN_HEADER_KEY_PREFIX = "admintoken ";


    public static String STAFF_SECRET = "staffsecret";
    public static String STAFF_HEADER_KEY = "staffauthorization";
    public static String STAFF_WPS_HEADER_KEY = "x-wps-weboffice-token";//wps
    public static String STAFF_HEADER_KEY_PREFIX = "stafftoken ";


    public static String MERCHANT_SECRET = "merchantsecret";
    public static String MERCHANT_HEADER_KEY = "merchantauthorization";
    public static String MERCHANT_HEADER_KEY_PREFIX = "merchanttoken ";


    @Resource
    private RedisUtil redisUtil;


    @Value("${debugRun}")
    private boolean debug;


    public String setStaffToken(StaffToken staffToken, HttpServletResponse response) {

        String token = createStaffToken(staffToken, System.currentTimeMillis());

        response.setHeader(JwtsUtil.STAFF_HEADER_KEY, token);

        return token;

    }


    public String setAdminToken(AdminToken staffToken, HttpServletResponse response) {
        String token = createAdminToken(staffToken, System.currentTimeMillis());
        response.setHeader(JwtsUtil.ADMIN_HEADER_KEY, token);
        return token;
    }

    public String setMerchantToken(MerchantToken staffToken, HttpServletResponse response) {
        String token = createMerchantToken(staffToken, System.currentTimeMillis());
        response.setHeader(JwtsUtil.MERCHANT_HEADER_KEY, token);
        return token;
    }


    public AdminToken getAdminToken(HttpServletRequest request) {
        String headerToken = request.getHeader(JwtsUtil.ADMIN_HEADER_KEY);
        return parseAdminToken(headerToken);
    }

    public MerchantToken getMerchantToken(HttpServletRequest request) {
        String headerToken = request.getHeader(JwtsUtil.MERCHANT_HEADER_KEY);
        return parseMerchantToken(headerToken);
    }


    public String getAdminId(HttpServletRequest request) {
        AdminToken token = getAdminToken(request);
        try {
            return token.getAdminId();
        } catch (Exception e) {

        }
        return "";
    }

    public String getAdminTruename(HttpServletRequest request) {

        AdminToken token = getAdminToken(request);
        try {
            return token.getTruename();
        } catch (Exception e) {

        }
        return "";

    }


    public String getMerchantId(HttpServletRequest request) {
        MerchantToken token = getMerchantToken(request);
        try {
            return token.getMerchantId();
        } catch (Exception e) {

        }
        return "";
    }


    public String getMerchantTruename(HttpServletRequest request) {

        MerchantToken token = getMerchantToken(request);
        try {
            return token.getMerchantTruename();
        } catch (Exception e) {

        }
        return "";

    }

    public String getMerchantMemberId(HttpServletRequest request) {

        MerchantToken token = getMerchantToken(request);
        try {
            return token.getMemberId();
        } catch (Exception e) {

        }
        return "";

    }

    public String getMerchantAccountNo(HttpServletRequest request) {

        MerchantToken token = getMerchantToken(request);
        try {
            return token.getAccountNo();
        } catch (Exception e) {

        }
        return "";

    }


    public StaffToken getStaffToken(HttpServletRequest request) {


        String headerToken = request.getHeader(JwtsUtil.STAFF_HEADER_KEY);

        if (debug) {
            StaffToken staffToken = new StaffToken();
            staffToken.setUsername("admin");
            staffToken.setStaffId("1");

            return staffToken;

        }

        if (StringUtil.isEmpty(headerToken)) {
            headerToken = request.getHeader(JwtsUtil.STAFF_WPS_HEADER_KEY);

        }


        return parseStaffToken(headerToken);

    }


    public String getMerchantIdByStaff(HttpServletRequest request) {

        StaffToken token = getStaffToken(request);
        try {

            String merchantId = token.getMerchantId();
            if (StringUtil.isNullOrEmpty(merchantId)) {
                return "-1";
            }
            return merchantId;
        } catch (Exception e) {

        }
        return "-1";

    }

    public String getStaffId(HttpServletRequest request) {

        StaffToken token = getStaffToken(request);
        try {
            return token.getStaffId();
        } catch (Exception e) {

        }
        return "";

    }

    public String getStaffCode(HttpServletRequest request) {

        StaffToken token = getStaffToken(request);
        try {
            return token.getCode();
        } catch (Exception e) {

        }
        return "";

    }

    public String getStaffTruename(HttpServletRequest request) {

        StaffToken token = getStaffToken(request);
        try {
            return token.getTruename();
        } catch (Exception e) {

        }
        return "";

    }

    public String getStaffNickname(HttpServletRequest request) {

        StaffToken token = getStaffToken(request);
        try {
            return token.getNickname();
        } catch (Exception e) {

        }
        return "";

    }


    public int getStaffOrAdminFlag(HttpServletRequest request) {

        StaffToken token = getStaffToken(request);
        try {
            return token.getStaffOrAdminFlag();
        } catch (Exception e) {

        }
        return 0;

    }

    public String getStaffCompanyName(HttpServletRequest request) {

        StaffToken token = getStaffToken(request);
        try {
            return token.getCompanyName();
        } catch (Exception e) {

        }
        return "";

    }

    public String getStaffPhone(HttpServletRequest request) {

        StaffToken token = getStaffToken(request);
        try {
            return token.getPhone();
        } catch (Exception e) {

        }
        return "";

    }


    public List<String> getStaffDeptIds(HttpServletRequest request) {

        StaffToken token = getStaffToken(request);
        try {
            return token.getDeptId();
        } catch (Exception e) {

        }
        return null;

    }

    public String getStaffDeptId(HttpServletRequest request) {

        try {
            return getStaffDeptIds(request).get(0);
        } catch (Exception e) {

        }
        return null;

    }


    /**
     * 移除
     *
     * @param token
     */
    public void removeToken(Token token) {

        if (token == null) {
            return;
        }
        try {

            String redisKey = token.getRedisKey();
            redisUtil.del(redisKey);

        } catch (Exception e) {

        }

    }

    /**
     * 判断是否要刷新
     * 5分钟内的需要刷新
     *
     * @param timeToken
     * @return
     */
    public boolean isRefreshToken(Token timeToken) {
        try {
            return System.currentTimeMillis() - timeToken.getCreateTime() > 60 * 5 * 1000;
        } catch (Exception e) {
        }
        return true;
    }


    public StaffToken parseStaffToken(String userToken) {
        String token = parseJWT(userToken, STAFF_SECRET, STAFF_HEADER_KEY_PREFIX);
        if (token == null) {
            return null;
        }
        try {
            return JSONObject.parseObject(token, StaffToken.class);
        } catch (Exception e) {
        }
        return null;
    }

    public MerchantToken parseMerchantToken(String userToken) {
        String token = parseJWT(userToken, MERCHANT_SECRET, MERCHANT_HEADER_KEY_PREFIX);
        if (token == null) {
            return null;
        }
        try {
            return JSONObject.parseObject(token, MerchantToken.class);
        } catch (Exception e) {
        }
        return null;
    }


    public String createStaffToken(StaffToken staffToken, long currentTime) {
        staffToken.setCreateTime(currentTime);
        return createToken(JSONObject.toJSONString(staffToken), STAFF_SECRET, currentTime, STAFF_HEADER_KEY_PREFIX);
    }

    public String createMerchantToken(MerchantToken staffToken, long currentTime) {
        staffToken.setCreateTime(currentTime);
        return createToken(JSONObject.toJSONString(staffToken), MERCHANT_SECRET, currentTime, MERCHANT_HEADER_KEY_PREFIX);
    }


    /**
     * 管理员token解密
     *
     * @param userToken
     * @return
     */
    public AdminToken parseAdminToken(String userToken) {
        String token = parseJWT(userToken, ADMIN_SECRET, ADMIN_HEADER_KEY_PREFIX);
        if (token == null) {
            return null;
        }
        try {
            return JSONObject.parseObject(token, AdminToken.class);
        } catch (Exception e) {

        }
        return null;
    }

    /**
     * 解密
     *
     * @param jsonWebToken
     * @param
     * @return
     */
    private String parseJWT(String jsonWebToken, String secret, String prefix) {
        try {
            String userToken = Jwts.parser().setSigningKey(secret).parseClaimsJws(jsonWebToken.replace(prefix, ""))

                    .getBody()

                    .getSubject();

            if (userToken == null) {
                return null;
            }
            String redisKey = JSONObject.parseObject(userToken, Token.class).getRedisKey();
            if (redisUtil.get(redisKey) == null) {
                return null;
            }
            return userToken;
        } catch (Exception e) {
            return null;
        }

    }

    private String createToken(String token, String secret, long currentTime, String prefix) {

        Token timeToken = JSONObject.parseObject(token, Token.class);

        redisUtil.set(timeToken.getRedisKey(), token, 60 * 60 * 24 * 1000);

        return prefix + Jwts.builder().setSubject(token).setExpiration(new Date(currentTime + 60 * 60 * 24 * 1000)).signWith(SignatureAlgorithm.HS512, secret)


                .compact();
    }

    /**
     * 创建管理员token
     *
     * @param adminToken
     * @param currentTime
     * @return
     */
    public String createAdminToken(AdminToken adminToken, long currentTime) {
        adminToken.setCreateTime(currentTime);
        return createToken(JSONObject.toJSONString(adminToken), ADMIN_SECRET, currentTime, ADMIN_HEADER_KEY_PREFIX);
    }

}
